/**
 * Fly_m at 2009-5-20
 */
package com.jay.nio.channel.clazz.selector;

import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.net.InetSocketAddress;

public class DownloadClient<T> implements Callable<T> {
	private FileChannel fileChannel;
	private static Selector selector;
	private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
	private String serverFileName;
	private String localFileName;

	public DownloadClient(String serverFileName, String localFileName) {
		this.serverFileName = serverFileName;
		this.localFileName = localFileName;
	}

	public T call() throws Exception {
		if (selector == null)
			selector = Selector.open();
		SocketChannel channel = SocketChannel.open();
		channel.configureBlocking(false);
		channel.connect(new InetSocketAddress("localhost", 1234));
		channel.register(selector, SelectionKey.OP_CONNECT);
		for (;;) {
			selector.select();
			Iterator<SelectionKey> keyIterator = selector.selectedKeys()
					.iterator();
			while (keyIterator.hasNext()) {
				SelectionKey key = keyIterator.next();
				keyIterator.remove();
				if (key.isConnectable()) {
					SocketChannel socketChannel = (SocketChannel) key.channel();
					if (socketChannel.isConnectionPending())
						socketChannel.finishConnect();
					socketChannel.write(ByteBuffer.wrap(serverFileName
							.getBytes()));
					socketChannel.register(selector, SelectionKey.OP_READ);
				}
				if (key.isReadable()) {
					SocketChannel socketChannel = (SocketChannel) key.channel();
					byteBuffer.clear();
					if (!socketChannel.isConnected())
						return null;
					if (fileChannel == null)
						fileChannel = new RandomAccessFile(localFileName, "rw")
								.getChannel();
					int r = socketChannel.read(byteBuffer);
					if (r <= 0) {
						if (fileChannel != null)
							fileChannel.close();
						channel.close();
						key.cancel();
						return null;
					}
					byteBuffer.flip();
					fileChannel.write(byteBuffer);
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			executorService.submit(new DownloadClient<Object>("d:/log4j.log",
					"d:/down" + i + ".log"));
		}
		executorService.shutdown();
	}
}
